﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using LeadThing.AbpZeroTemplate.Areas;
using LeadThing.AbpZeroTemplate.Authorization.Roles;
using LeadThing.AbpZeroTemplate.Authorization.Roles.Dto;
using LeadThing.AbpZeroTemplate.Authorization.Users;
using LeadThing.AbpZeroTemplate.Dto;
using LeadThing.AbpZeroTemplate.Files;
using LeadThing.AbpZeroTemplate.Files.Dtos;
using LeadThing.AbpZeroTemplate.FireFightingWorks.Authorization;
using LeadThing.AbpZeroTemplate.FireFightingWorks.Dtos;
using static LeadThing.AbpZeroTemplate.Configuration.AppSettings;

namespace LeadThing.AbpZeroTemplate.FireFightingWorks
{
    /// <summary>
    /// 消防工作服务实现
    /// </summary>



    public class FireFightingWorkAppService : AbpZeroTemplateAppServiceBase, IFireFightingWorkAppService
    {
        private readonly IRepository<FireFightingWork, long> _fireFightingWorkRepository;
        private readonly IFireFightingWorkListExcelExporter _fireFightingWorkListExcelExporter;
        private readonly IRepository<File, long> _fileRepository;
        private readonly IRepository<User, long> _userRepository;//用户
        private readonly IRoleAppService _roleService;//角色
        private readonly IRepository<Area, long> _areaRepository;
        private readonly ISqlExecuter _sqlExecuter;//sql语句接口


        private readonly FireFightingWorkManage _fireFightingWorkManage;
        private readonly IFileAppService _fileAppService;
        /// <summary>
        /// 构造方法
        /// </summary>
        public FireFightingWorkAppService(IRepository<FireFightingWork, long> fireFightingWorkRepository
      , FireFightingWorkManage fireFightingWorkManage
      , IFireFightingWorkListExcelExporter fireFightingWorkListExcelExporter
      , IRepository<File, long> fileRepository
      , IFileAppService fileAppService
      , IRepository<User, long> userRepository
      , IRoleAppService roleService
      , IRepository<Area, long> areaRepository
      , ISqlExecuter sqlExecuter
  )
        {
            _fireFightingWorkRepository = fireFightingWorkRepository;
            _fireFightingWorkManage = fireFightingWorkManage;
            _fireFightingWorkListExcelExporter = fireFightingWorkListExcelExporter;
            _fileRepository = fileRepository;
            _fileAppService = fileAppService;
            _userRepository = userRepository;
            _roleService = roleService;
            _areaRepository = areaRepository;
            _sqlExecuter = sqlExecuter;
        }


        #region 实体的自定义扩展方法
        private IQueryable<FireFightingWork> _fireFightingWorkRepositoryAsNoTrack => _fireFightingWorkRepository.GetAll().AsNoTracking();

        /// <summary>
        /// 获取全部消防工作加载到前台地图
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public List<FireFightingWorkLoadPageDto> GetAllFireFightingWorksLoadPage(GetFireFightingWorkInput input)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(@" select *,
                        'TownTitle' = (select Title from Basic.Area where id = f.TownID),
                        'AreaTitle' = (select Title from Basic.Area where id = f.AreaID),
                        'VillageTitle' = (select Title from Basic.Area where id = f.VillageID),
                         'XPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 XPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                          ,'YPoint' =
                            CASE
                                WHEN [VillageID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [VillageID])
                                WHEN [AreaID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [AreaID])
                                WHEN [TownID] > 0 THEN (select top 1 YPoint from Basic.Area where Id = [TownID])
                                ELSE ''
                            END
                        from Basic.FireFightingWork f where isDeleted=0 ");

            if (!string.IsNullOrWhiteSpace(input.Filter))
            {
                sb.Append(" and Title like '%");
                sb.Append(input.Filter);
                sb.Append("%' ");
            }

            var list = _sqlExecuter.SqlQuery<FireFightingWorkLoadPageDto>(sb.ToString()).ToList();
            foreach (var item in list)
            {
                item.fileList = _fileRepository.GetAll().Where(p => p.DisID == item.Id).ToList().MapTo<List<FileListDto>>();
            }

            return list;
        }

        #endregion


        #region 消防工作管理

        /// <summary>
        /// 根据查询条件获取消防工作分页列表
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork)]
        public async Task<PagedResultDto<FireFightingWorkListDto>> GetPagedFireFightingWorksAsync(GetFireFightingWorkInput input)
        {
            var query = _fireFightingWorkRepositoryAsNoTrack;
            //TODO:根据传入的参数添加过滤条件

            #region 权限验证

            var userID = AbpSession.GetUserId();
            var userModel = _userRepository.FirstOrDefault(userID);
            GetRolesInput input_role = new GetRolesInput() { UserId = userID };
            var role = await _roleService.GetRolesByUserId(input_role);

            if (role.DisplayName == "乡镇网格管理员")
                query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
            else if (role.DisplayName == "社区网格管理员")
                query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
            else if (role.DisplayName == "村庄网格管理员")
                query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);

            #endregion

            if (!string.IsNullOrWhiteSpace(input.Filter))
            {
                query = query.Where(p => p.Title.Contains(input.Filter));
            }

            var fireFightingWorkCount = await query.CountAsync();

            var items = await query
            .OrderBy(input.Sorting)
            .OrderByDescending(p => p.Id)
            .ToListAsync();

            var areaList = _areaRepository.GetAll();
            return new PagedResultDto<FireFightingWorkListDto>(
            fireFightingWorkCount,
            items.Select(item =>
            {
                var dto = item.MapTo<FireFightingWorkListDto>();
                var townModel = areaList.Where(p => p.Id == dto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                if (townModel != null)
                    dto.TownTitle = townModel.Title;

                var areaModel = areaList.Where(p => p.Id == dto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                if (areaModel != null)
                    dto.AreaTitle = areaModel.Title;

                var villModel = areaList.Where(p => p.Id == dto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                if (villModel != null)
                    dto.VillageTitle = villModel.Title;

                return dto;
            }).ToList());
        }

        /// <summary>
        /// 通过Id获取消防工作信息进行编辑或修改 
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork)]
        public async Task<GetFireFightingWorkForEditOutput> GetFireFightingWorkForEditAsync(NullableIdDto<long> input)
        {
            var output = new GetFireFightingWorkForEditOutput();

            FireFightingWorkEditDto fireFightingWorkEditDto;

            if (input.Id.HasValue)
            {
                var entity = await _fireFightingWorkRepository.GetAsync(input.Id.Value);
                fireFightingWorkEditDto = entity.MapTo<FireFightingWorkEditDto>();

                fireFightingWorkEditDto.Files = _fileRepository.GetAll().Where(p => p.DisID == entity.Id).ToList().Select(item =>
                {
                    var dto = item.MapTo<FileListDto>();
                    dto.Url = AppSetting.AppUrl + item.Url;
                    return dto;
                }).ToList();
            }
            else
            {
                fireFightingWorkEditDto = new FireFightingWorkEditDto();
            }

            output.FireFightingWork = fireFightingWorkEditDto;
            return output;
        }


        /// <summary>
        /// 通过指定id获取消防工作ListDto信息
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork)]
        public async Task<FireFightingWorkListDto> GetFireFightingWorkByIdAsync(EntityDto<long> input)
        {
            var entity = await _fireFightingWorkRepository.GetAsync(input.Id);

            return entity.MapTo<FireFightingWorkListDto>();
        }







        /// <summary>
        /// 新增或更改消防工作
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork)]
        public async Task CreateOrUpdateFireFightingWorkAsync(CreateOrUpdateFireFightingWorkInput input)
        {
            if (input.FireFightingWorkEditDto.Id.HasValue)
            {
                await UpdateFireFightingWorkAsync(input.FireFightingWorkEditDto);
            }
            else
            {
                await CreateFireFightingWorkAsync(input.FireFightingWorkEditDto);
            }
        }

        /// <summary>
        /// 新增消防工作
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork_CreateFireFightingWork)]
        public virtual async Task<FireFightingWorkEditDto> CreateFireFightingWorkAsync(FireFightingWorkEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<FireFightingWork>();

            entity = await _fireFightingWorkRepository.InsertAsync(entity);
            return entity.MapTo<FireFightingWorkEditDto>();
        }

        /// <summary>
        /// 编辑消防工作
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork_EditFireFightingWork)]
        public virtual async Task UpdateFireFightingWorkAsync(FireFightingWorkEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新

            var entity = await _fireFightingWorkRepository.GetAsync(input.Id.Value);
            input.MapTo(entity);

            await _fireFightingWorkRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除消防工作
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork_DeleteFireFightingWork)]
        public async Task DeleteFireFightingWorkAsync(EntityDto<long> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _fireFightingWorkRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 批量删除消防工作
        /// </summary>
        [AbpAuthorize(FireFightingWorkAppPermissions.FireFightingWork_DeleteFireFightingWork)]
        public async Task BatchDeleteFireFightingWorkAsync(List<long> input)
        {
            //TODO:批量删除前的逻辑判断，是否允许删除
            await _fireFightingWorkRepository.DeleteAsync(s => input.Contains(s.Id));
        }

        #endregion

        #region 消防工作的Excel导出功能


        public async Task<FileDto> GetFireFightingWorkToExcel()
        {
            var entities = await _fireFightingWorkRepository.GetAll().ToListAsync();

            var dtos = entities.MapTo<List<FireFightingWorkListDto>>();

            var fileDto = _fireFightingWorkListExcelExporter.ExportFireFightingWorkToFile(dtos);



            return fileDto;
        }


        #endregion

        #region APP

        /// <summary>
        /// 根据查询条件获取消防工作分页列表
        /// </summary>
        public async Task<PagedResultDto<FireFightingWorkAPPListDto>> GetPagedFireFightingWorksAPPAsync(GetFireFightingWorkAPPInput input)
        {
            var _pageIndex = Convert.ToInt32(input.PageIndex);
            var _pageSize = Convert.ToInt32(input.PageSize);
            var query = _fireFightingWorkRepositoryAsNoTrack;
            //TODO:根据传入的参数添加过滤条件

            #region 权限验证

            if (!string.IsNullOrWhiteSpace(input.UserId))
            {
                var userID = Convert.ToInt32(input.UserId);
                var userModel = _userRepository.FirstOrDefault(userID);
                GetRolesInput input_role = new GetRolesInput() { UserId = userID };
                var role = await _roleService.GetRolesByUserId(input_role);

                if (role.DisplayName == "乡镇网格管理员")
                    query = query.Where(p => p.TownID == userModel.TownID || p.CreatorUserId == userID);
                else if (role.DisplayName == "社区网格管理员")
                    query = query.Where(p => p.AreaID == userModel.AreaID || p.CreatorUserId == userID);
                else if (role.DisplayName == "村庄网格管理员")
                    query = query.Where(p => p.VillageID == userModel.VillageID || p.CreatorUserId == userID);
            }

            #endregion

            var fireFightingWorkCount = await query.CountAsync();

            var fireFightingWorks = await query
            .OrderByDescending(p => p.Id)
            .Take(_pageSize * _pageIndex).Skip(_pageSize * (_pageIndex - 1))
            .ToListAsync();

            var fireFightingWorkListDtos = fireFightingWorks.MapTo<List<FireFightingWorkAPPListDto>>();
            return new PagedResultDto<FireFightingWorkAPPListDto>(
            fireFightingWorkCount,
            fireFightingWorkListDtos
            );
        }

        /// <summary>
        /// 新增消防工作
        /// </summary>
        public virtual async Task<FireFightingWorkAPPEditDto> CreateFireFightingWorkAPPAsync(FireFightingWorkAPPEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<FireFightingWork>();
            var id = await _fireFightingWorkRepository.InsertAndGetIdAsync(entity);

            if (id == 0)
            {
                throw new UserFriendlyException("新增失败！");
            }

            if (string.IsNullOrWhiteSpace(input.FileIds))
            {
                throw new UserFriendlyException("请至少上传一张图片");
            }
            //批量修改文件表
            string[] array = input.FileIds.Split(',');
            for (int i = 0; i < array.Length; i++)
            {
                if (!string.IsNullOrWhiteSpace(array[i]))
                {
                    var fileId = Convert.ToInt32(array[i]);
                    var fileModel = await _fileAppService.GetFileForEditAPPAsync(fileId);
                    fileModel.DisID = Convert.ToInt32(id);
                    await _fileAppService.UpdateFileAsync(fileModel);
                }
            }

            var returnEntity = entity.MapTo<FireFightingWorkAPPEditDto>();
            returnEntity.FileIds = input.FileIds;
            return returnEntity;
        }

        /// <summary>
        /// 通过Id获取消防工作信息进行编辑或修改 
        /// </summary>
        public async Task<FireFightingWorkGetModelAPPEditDto> GetFireFightingWorkForEditAPPAsync(EntityDto<string> input)
        {
            var _id = Convert.ToInt32(input.Id);
            FireFightingWorkGetModelAPPEditDto fireFightingWorkEditDto;

            if (_id > 0)
            {
                var entity = await _fireFightingWorkRepository.GetAsync(_id);
                fireFightingWorkEditDto = entity.MapTo<FireFightingWorkGetModelAPPEditDto>();

                fireFightingWorkEditDto.Files = _fileRepository.GetAll().Where(p => p.DisID == entity.Id).ToList().Select(item =>
                {
                    var dto = item.MapTo<FileListDto>();
                    dto.Url = AppSetting.AppUrl + item.Url;
                    return dto;
                }).ToList();

                var areaList = _areaRepository.GetAll();
                var townModel = areaList.Where(p => p.Id == fireFightingWorkEditDto.TownID).Select(p => new { p.Title }).FirstOrDefault();
                if (townModel != null)
                    fireFightingWorkEditDto.TownTitle = townModel.Title;

                var areaModel = areaList.Where(p => p.Id == fireFightingWorkEditDto.AreaID).Select(p => new { p.Title }).FirstOrDefault();
                if (areaModel != null)
                    fireFightingWorkEditDto.AreaTitle = areaModel.Title;

                var villModel = areaList.Where(p => p.Id == fireFightingWorkEditDto.VillageID).Select(p => new { p.Title }).FirstOrDefault();
                if (villModel != null)
                    fireFightingWorkEditDto.VillageTitle = villModel.Title;
            }
            else
            {
                fireFightingWorkEditDto = new FireFightingWorkGetModelAPPEditDto();
            }
            return fireFightingWorkEditDto;
        }

        #endregion

    }
}
